﻿using SAIM.Models.DAL;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;

namespace SAIM.Models.BLL
{
    public class TicketCommentsBLL : IDisposable
    {
        private SAIMEntities db;
        private DbSet<TicketCommentsDAL> _value;

        /// <summary>
        /// DAL TicketComments. It contains all tickets comments.
        /// </summary>
        public DbSet<TicketCommentsDAL> Value 
        {
            get { return (_value = _value ?? db.TicketComments); }
            set { _value = value; }
        }

        public enum TicketCommentsMessage
        {
            FileUploadCommentAdded,
            FileUploadCommentEdited,
            FileUploadCommentException,
            CommentAdded,
            CommentEdited,
            CommentException
        }

        /// <summary>
        /// It represents a Ticket Comment for BLL. Interacts with the database and DAL to get the mapped information.
        /// </summary>
        public TicketCommentsBLL()
        {
            db = new SAIMEntities();
        }

        /// <summary>
        /// Inserts a new ticket comment into the data base
        /// </summary>
        /// <param name="_TicketId">Ticket ID</param>
        /// <param name="_UserId">USer ID</param>
        /// <param name="_Details">Details of comment</param>
        /// <param name="_CommentDate">Date of comment</param>
        /// <param name="_IsPrivate">Comment Type { true: Private, false: Public}</param>
        /// <param name="_HasAttachedFiles">Indica si el comentario cuenta con archivos adjuntos</param>
        /// <returns></returns>
        public TicketCommentsMessage insertComment(long _TicketId, string _UserId, string _Details, DateTime _CommentDate, bool _IsPrivate, bool _HasAttachedFiles)
        {
            TicketsDAL ticket = db.Tickets.FirstOrDefault(a => a.Id == _TicketId);
            #region Creación del nuevo comentario
            TicketCommentsDAL comment = new TicketCommentsDAL()
            {
                TicketId = _TicketId,
                UserId = _UserId,
                Details = _Details,
                CommentDate = _CommentDate,
                IsPrivate = _IsPrivate,
                CanEdit = true,
                HasAttachments = false
            };
            #endregion
            // Se verifica que el comentario tenga o no archivos adjuntos
            if (_HasAttachedFiles)
            {
                TicketCommentsDAL lastEditionComent = ticket.TicketComments.LastOrDefault(c => (c.TicketId == _TicketId)
                && (c.UserId == _UserId)
                && (c.CommentDate.Year == _CommentDate.Year)
                && (c.CommentDate.Month == _CommentDate.Month)
                && (c.CommentDate.Day == _CommentDate.Day)
                && (c.CommentDate.Hour == _CommentDate.Hour)
                && (!c.CanEdit));
                // Se verifica que el ultimo comentario corresponda a los archivos adjuntos y se le agrega el comentario
                if (lastEditionComent != null)
                {
                    try
                    {
                        ticket.TicketStatus = ticket.UserId == _UserId ? "En espera de respuesta administrador" : "En espera de respuesta usuario";
                        lastEditionComent.Details = _Details + "<br/>" + lastEditionComent.Details;
                        lastEditionComent.HasAttachments = true;
                        db.SaveChanges();
                        return TicketCommentsMessage.CommentEdited;
                    }
                    catch (Exception) { return TicketCommentsMessage.CommentException; }
                }
                else // Si no existe el comentario con los archivos adjuntos se agrega uno nuevo
                {
                    try
                    {
                        ticket.TicketStatus = ticket.UserId == _UserId ? "En espera de respuesta administrador" : "En espera de respuesta usuario";
                        db.TicketComments.Add(comment);
                        db.SaveChanges();
                        return TicketCommentsMessage.CommentAdded;
                    }
                    catch (Exception) { return TicketCommentsMessage.CommentException; }
                }
            }
            else // Si el comentario no cuenta con archivos adjuntos se agrega uno nuevo al ticket
            {
                try
                {
                    ticket.TicketStatus = ticket.UserId == _UserId ? "En espera de respuesta administrador" : "En espera de respuesta usuario";
                    db.TicketComments.Add(comment);
                    db.SaveChanges();
                    return TicketCommentsMessage.CommentAdded;
                }
                catch (Exception) { return TicketCommentsMessage.CommentException; }
            }
        }

        /// <summary>
        /// Edits a ticket comment 
        /// </summary>
        /// <param name="_TicketId"></param>
        /// <param name="_UserId"></param>
        /// <param name="_CommentId"></param>
        /// <param name="_Details"></param>
        /// <param name="_CommentDate"></param>
        /// <returns></returns>
        public bool editComment(long _TicketId, string _UserId, long _CommentId, string _Details, DateTime _CommentDate)
        {
            TicketCommentsDAL comment = Value.FirstOrDefault(c => c.Id == _CommentId);
            TicketCommentEditionsDAL lastEdition = db.TicketCommentEditions.ToList().LastOrDefault();

            TicketCommentEditionsDAL edition = new TicketCommentEditionsDAL
            {
                CommentDate = comment.CommentDate,
                CommentId = _CommentId,
                Details = comment.Details,
                Id = lastEdition != null ? lastEdition.Id + 1 : 1
            };
            comment.Details = _Details;
            comment.CommentDate = DateTime.Now;
            try
            {
                db.TicketCommentEditions.Add(edition);
                db.SaveChanges();
            }
            catch (Exception) { return false; }
            return true;
        }

        public ICollection<TicketCommentEditionsDAL> GetEditions(long _CommentId)
        {
            try
            {
                return Value.FirstOrDefault(c => c.Id == _CommentId).TicketCommentEdition;
            }
            catch (Exception) { return new List<TicketCommentEditionsDAL>(); }
        }

        public TicketCommentsMessage NewAttachmentComment(long _TicketId, string _UserId, DateTime _CommentDate, HttpPostedFileBase file, string hashName, string host)
        {
            TicketsDAL ticket = db.Tickets.FirstOrDefault(a => a.Id == _TicketId);
            TicketCommentsDAL comment = new TicketCommentsDAL()
            {
                TicketId = _TicketId,
                UserId = _UserId,
                Details = "Se <b>adjuntó</b> el siguiente archivo:&nbsp; <i class=\"glyphicon glyphicon-file\" aria-hidden=\"true\"></i> <span><a href=\"" + host + "/Tickets/GetAttachedFile/" + _TicketId.ToString() +  "?attachmentId=" + hashName + "\">" + file.FileName + "</a></span>",
                CommentDate = _CommentDate,
                IsPrivate = false,
                CanEdit = false
            };
            TicketCommentsDAL lastEditionComent = ticket.TicketComments.LastOrDefault(c => (c.TicketId == _TicketId)
                && (c.UserId == _UserId)
                && (c.CommentDate.Year == _CommentDate.Year)
                && (c.CommentDate.Month == _CommentDate.Month)
                && (c.CommentDate.Day == _CommentDate.Day)
                && (c.CommentDate.Hour == _CommentDate.Hour)
                && (!c.CanEdit)
                && (c.HasAttachments == null || !c.HasAttachments.Value));
            if ((lastEditionComent != null) && (!lastEditionComent.CanEdit))
            {
                try
                {
                    ticket.TicketStatus = ticket.UserId == _UserId ? "En espera de respuesta administrador" : "En espera de respuesta usuario";
                    lastEditionComent.Details += "<br/>Se <b>adjuntó</b> el siguiente archivo:&nbsp; <i class=\"glyphicon glyphicon-file\" aria-hidden=\"true\"></i> <span><a href=\"" + host + "/Tickets/GetAttachedFile/" + _TicketId.ToString() + "?attachmentId=" + hashName + "\">" + file.FileName + "</a></span>";
                    db.SaveChanges();
                    return TicketCommentsMessage.FileUploadCommentEdited;
                }
                catch (Exception) { return TicketCommentsMessage.FileUploadCommentException; }
            }
            else
            {
                try
                {
                    ticket.TicketStatus = ticket.UserId == _UserId ? "En espera de respuesta administrador" : "En espera de respuesta usuario";
                    db.TicketComments.Add(comment);
                    db.SaveChanges();
                    return TicketCommentsMessage.FileUploadCommentAdded;
                }
                catch (Exception) { return TicketCommentsMessage.FileUploadCommentException; }
            }
        }

        /// <summary>
        /// Devuelve un comentario 
        /// </summary>
        /// <param name="ticketId">ID del ticket donde se encuentra el comentario</param>
        /// <param name="userId">ID del usuario que ralizo el comentario</param>
        /// <param name="commentId">ID del comentario</param>
        /// <returns></returns>
        public TicketComment GetTicketComment(long ticketId, string userId, long commentId)
        {
            TicketComment comment;
            TicketCommentsDAL entitie;

            try 
            {
                entitie = (from e in db.TicketComments 
                           where ((e.TicketId == ticketId) && 
                               (e.UserId == userId) && 
                               (e.Id == commentId)) 
                           select e).FirstOrDefault();
                comment = new TicketComment()
                {
                    CanEdit = entitie.CanEdit,
                    Comment = entitie.Details,
                    CommentDate = entitie.CommentDate,
                    EditionsCount = entitie.TicketCommentEdition.Count,
                    HasAttachedFiles = entitie.HasAttachments ?? false,
                    IdComment = entitie.Id,
                    IdTicket = entitie.TicketId,
                    IsPrivate = entitie.IsPrivate,
                    UserId = entitie.UserId,
                    UserName = entitie.AspNetUsers.UserName
                };
            }
            catch (Exception) 
            {
                comment = null;
            }

            return comment;
        }

        public void Dispose()
        {
            db.Dispose();
        }
    }
}